home *** CD-ROM | disk | FTP | other *** search
- /************************************************
- * help.c - demo program shows a new way to
- * present on-line help
- *
- * Bill Rausch, Jan 1987
- * Uses LightSpeed C™ (Think Technologies, Inc.)
- ***********************************************/
-
- #include <EventMgr.h>
- #include <MenuMgr.h>
- #include <WindowMgr.h>
- #include <ToolboxUtil.h>
- #include <DialogMgr.h>
- #include <FontMgr.h>
- #include <TextEdit.h>
- #include <ListMgr.h>
- #include <strings.h>
- #include <pascal.h>
-
- #define NULL 0L
- #define ACTIVATE 0
- #define INACTIVATE 255
-
- #define FILEID 256
- #define ABOUT 1
- #define HELP 2
- #define QUIT 3
-
- #define HELP_DLG 256
- #define HELP_OK 1
- #define HELP_BOX 2
- #define HELP_LIST 3
-
- #define HELP_STR 256 /* STR# containing topics */
- #define MAX_HELPS 100 /* application dependent */
-
- struct {
- Rect text_box; /* user item dimensions */
- Rect topic_box; /* user item dimensions */
- TEHandle text;
- ListHandle topics;
- Rect d_rect; /* TextEdit's dest rect */
- Rect v_rect; /* TextEdit's view rect */
- int offset; /* d_rect vertical shift */
- int lines_vis; /* number of lines visible */
- ControlHandle text_scroll;
- int max_text; /* max value of scroller */
- int help_id[MAX_HELPS]; /* topics’ HELP IDs */
- int num_topics; /* how many topics? */
- int last_one; /* last cell clicked in */
- } h;
-
- pascal Boolean help_filter();
- Boolean show_help();
- pascal void help_action();
-
- /************************************************
- * Trivial main(), just enough to use a single
- * menu with only three items: About..., Help...,
- * and Quit. No DAs, no windows, no command key
- * equivalents or other key strokes. */
- main()
- {
- EventRecord the_event;
- WindowPtr which_window;
- int menu_id, item_number;
- long menu_code;
- int window_code;
- MenuHandle filemenu;
-
- FlushEvents(everyEvent, 0);
- InitGraf(&thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(NULL);
-
- filemenu = GetMenu(FILEID);
- InsertMenu(filemenu, 0);
- DrawMenuBar();
- InitCursor();
-
- for (;;) /* event loop */
- {
- if (GetNextEvent(everyEvent, &the_event))
- {
- if (the_event.what == mouseDown)
- {
- window_code = FindWindow(the_event.where,
- &which_window);
- if (window_code == inMenuBar)
- {
- menu_code = MenuSelect(the_event.where);
- menu_id = HiWord(menu_code);
- item_number = LoWord(menu_code);
- if (menu_id == FILEID)
- {
- if (item_number == ABOUT)
- do_about(
- "Help demo - Bill Rausch - Jan. 1987",
- "LightSpeed C™ by Think Technologies");
- else if (item_number == HELP)
- do_help(HELP_STR);
- else if (item_number == QUIT)
- ExitToShell();
- else
- SysBeep(1);
- }
- HiliteMenu(0);
- DrawMenuBar();
- }
- else
- SysBeep(1);
- }
- else
- SysBeep(1);
- }
- }
- }
-
- /***********************************************/
- /* creates alert-like box, waits for mouseDown */
- do_about(text1, text2)
- char *text1, *text2;
- {
- long dummy;
- Rect box;
- Rect line;
- GrafPtr old_port;
- WindowPtr window;
- EventRecord an_event;
-
- SetRect(&line, 6, 5, 345, 25);
- SetRect(&box, 75, 125, 425, 180);
- window = NewWindow(NULL, &box, "", TRUE,
- dBoxProc, -1L, TRUE, NULL);
- GetPort(&old_port);
- SetPort(window);
-
- TextFont(systemFont);
- TextBox(text1, (long)strlen(text1), &line,
- teJustCenter);
- OffsetRect(&line, 0, 28);
- TextBox(text2, (long)strlen(text2), &line,
- teJustCenter);
-
- do {
- GetNextEvent(everyEvent, &an_event);
- } while (an_event.what != mouseDown);
-
- DisposeWindow(window);
- SetPort(old_port);
- }
-
- /************************************************
- * Help routine that makes use of the List
- * Manager to present user with a list of topics
- * and help text about each one. The topics are
- * stored as a STR# resource and the help texts
- * are stored as HELP resources. Each topic
- * string contains the number of its associated
- * HELP resource.
- * Note: requires Geneva 10 font to be present */
- do_help(str_id)
- int str_id;
- {
- DialogPtr the_dialog;
- Handle scr_handle; /* scratch variable */
- int scratch; /* scratch variable */
- Str255 scr_str; /* scratch variable */
- Rect hdata_rect; /* for list manager setup */
- Point cell_size; /* for list manager setup */
- Handle topics; /* for list manager setup */
- int *n_t_ptr;
- GrafPtr old_port;
-
- /* Read STR#, get number topics */
- topics = GetResource('STR#', str_id);
- h.num_topics = *(int *)(*topics);
-
- /* Read dialog box resource */
- the_dialog = GetNewDialog(HELP_DLG, NULL, -1L);
- GetPort(&old_port); /* save where we were */
- SetPort(the_dialog);
-
- /* get user item for topic list */
- GetDItem(the_dialog, HELP_LIST, &scratch,
- &scr_handle, &h.topic_box);
- InsetRect(&h.topic_box, 1, 1);
- /* leave room for vertical scroll bar */
- h.topic_box.right -= 15;
- SetRect(&hdata_rect, 0, 0, 1, h.num_topics);
- SetPt(&cell_size, h.topic_box.right -
- h.topic_box.left, 16);
-
- h.topics = LNew(&h.topic_box, &hdata_rect,
- cell_size, 0, the_dialog,
- FALSE, FALSE, FALSE, TRUE);
- (*h.topics)->selFlags = lOnlyOne;
- /* restore rect for framing */
- InsetRect(&h.topic_box, -1, -1);
- read_help(h.topics,h.num_topics,h.help_id,str_id);
-
- if (!show_help(the_dialog, h.topics,
- h.help_id))
- do_about("show_help()",
- "returned an error.");
-
- SetPort(old_port); /* put us back */
- }
-
- /************************************************
- * Read the topics from the STR# resource. Add
- * them to the List as they are read. Also, save
- * the IDs in an array for use later in finding
- * the proper HELP resource to display for each
- * topic. */
- read_help(topics, num_topics, help_id,
- str_id)
- ListHandle topics;
- int num_topics;
- int help_id[];
- int str_id;
- {
- int i;
- Str255 a_topic;
- Point the_cell;
- char *id_number;
- Str255 strvar;
-
- for (i=0; i<num_topics; i++)
- {
- GetIndString(a_topic, str_id, i+1);
- PtoCstr(a_topic);
- id_number = strchr(a_topic, (char)'\\');
-
- /* terminate topic and point to number */
- *id_number++ = '\0';
- help_id[i] = atoi(id_number);
-
- SetPt(&the_cell, 0, i);
- LSetCell(a_topic, strlen(a_topic), the_cell,
- topics);
- }
-
- SetPt(&the_cell, 0, 0);
- LSetSelect((Boolean)TRUE, the_cell, topics);
- LDoDraw((Boolean)TRUE, topics);
- }
-
- /************************************************
- * Set up the help text for the first topic in
- * the list. Call ModalDialog (with a filterProc
- * to do all the work). Loop until user clicks
- * OK. */
- Boolean show_help(the_dialog, topics, help_id)
- DialogPtr the_dialog;
- ListHandle topics;
- int help_id[];
- {
- GrafPtr old_port;
- int item_hit; /* returned by ModalDialog */
- int scr_int; /* scratch variable */
- Handle scr_handle; /* scratch variable */
- Boolean done = FALSE;
- int i, buf_size;
- Rect scroll_rect;
- Handle the_help;
-
- /* get user item for help text */
- GetDItem(the_dialog, HELP_BOX, &scr_int,
- &scr_handle, &h.text_box);
- /* leave room for scroll bar */
- h.text_box.right -= 16;
- scroll_rect.right = h.text_box.right + 15;
- scroll_rect.left = h.text_box.right - 1;
- scroll_rect.top = h.text_box.top;
- scroll_rect.bottom = h.text_box.bottom;
- h.text_scroll = NewControl(the_dialog,
- &scroll_rect, "", TRUE,
- 0, 0, 0, 16, NULL);
- HiliteControl(h.text_scroll, INACTIVATE);
-
- /* Set up TextEdit record for the help text */
- h.d_rect.top = h.text_box.top + 1;
- h.d_rect.left = h.text_box.left + 1;
- h.d_rect.right = h.text_box.right - 1;
- h.d_rect.bottom = 20000; /* infinity */
- h.v_rect = h.text_box;
- InsetRect(&h.v_rect, 1, 1);
- h.text = TENew(&h.d_rect, &h.v_rect);
- (*h.text)->txFont = geneva;
- (*h.text)->txSize = 10;
-
- h.last_one = 0; /* 1st topic selected */
- h.offset = 0; /* at top left corner now */
- h.lines_vis = (h.v_rect.bottom - h.v_rect.top)
- / (*h.text)->lineHeight;
-
- /* put 1st topic’s text into help box */
- the_help = GetResource('HELP', help_id[0]);
- buf_size = SizeResource(the_help);
- TEDeactivate(h.text);
- TESetSelect(32767L, 32767L, h.text);
- HLock(the_help);
- TEInsert(*the_help, (long)buf_size, h.text);
- HUnlock(the_help);
-
- /* vertical scroll bar necessary? */
- if ((*h.text)->nLines > h.lines_vis)
- {
- HiliteControl(h.text_scroll, ACTIVATE);
- h.max_text = (((*h.text)->nLines) -
- h.lines_vis) * (*h.text)->lineHeight;
- SetCtlMax(h.text_scroll, h.max_text);
- }
-
- ShowWindow(the_dialog);
- do {
- ModalDialog(help_filter, &item_hit);
- if (item_hit == HELP_OK)
- done = TRUE;
- } while (!done);
-
- TEDispose(h.text);
- LDispose(h.topics);
- DisposDialog(the_dialog);
- return TRUE;
- }
-
-
- /************************************************
- * This routine handles activating and updating
- * of the scroller and the box area. We must
- * handle mouse downs in the scroller and text
- * box, passing back TRUE, and pass FALSE back
- * for everything else so the Dialog Manager does
- * his thing on the other items. */
- pascal Boolean help_filter(dp, ep, ip)
- WindowPtr dp;
- EventRecord *ep;
- int *ip;
- {
- int part;
- ControlHandle ch;
- char tempchar; /* check keydown for RETURN */
- Point mouse_loc;
- int start_value, end_value, dummy, delta;
- long a_cell;
- int cell_num;
- Handle the_help;
- int buf_size;
- int scr_int; /* scratch variable */
- Handle scr_handle; /* scratch variable */
- Rect scr_rect; /* scratch variable */
-
- switch(ep->what)
- {
- case updateEvt:
- /* is the update event for this window? */
- if (ep->message == (long)dp)
- {
- /* outline default button */
- GetDItem(dp, HELP_OK, &scr_int,
- &scr_handle, &scr_rect);
- InsetRect(&scr_rect, -4, -4);
- PenSize(3, 3);
- FrameRoundRect(&scr_rect, 16, 16);
- PenNormal();
- /* draw boxes around topics, text */
- FrameRect(&h.topic_box);
- FrameRect(&h.text_box);
- /* update contents of boxes */
- EraseRect(&h.v_rect);
- TEUpdate(&h.v_rect, h.text);
- LUpdate(dp->visRgn, h.topics);
- }
- return FALSE;
-
- case keyDown:
- /* convert return key to OK button */
- tempchar = BitAnd(ep->message,
- charCodeMask);
- if (tempchar == '\r')
- {
- *ip = HELP_OK;
- return TRUE;
- }
- return FALSE;
-
- case mouseDown:
- /* get our own copy of coordinates */
- mouse_loc = ep->where;
- GlobalToLocal(&mouse_loc);
-
- part = FindControl(mouse_loc, dp, &ch);
- if (part > 0)
- {
- /* is click in a scroll bar? */
- if (ch == h.text_scroll)
- {
- if (part == inThumb)
- {
- if(TrackControl(ch, mouse_loc, NULL))
- {
- /* reposition help text */
- delta = h.offset -
- GetCtlValue(h.text_scroll);
- TEScroll(0, delta, h.text);
- h.offset -= delta;
- }
- }
- else
- TrackControl(ch, mouse_loc,
- help_action);
- return TRUE;
- }
- else if (ch == (*h.topics)->vScroll)
- {
- LClick(mouse_loc, ep->modifiers,
- h.topics);
- return TRUE;
- }
- else
- return FALSE;
- }
- else if (PtInRect(mouse_loc, *h.topics))
- {
- /* click was in topics list so find which
- * topic was selected and display the
- * proper HELP resource */
- LClick(mouse_loc, ep->modifiers,
- h.topics);
- a_cell = 0;
- if (LGetSelect(TRUE, &a_cell, h.topics))
- cell_num = HiWord(a_cell);
- if (cell_num >= 0 &&
- cell_num != h.last_one)
- {
- /* get rid of the old text */
- TEDeactivate(h.text);
- TESetSelect(0L, 32767L, h.text);
- TEDelete(h.text);
- if (cell_num < h.num_topics)
- {
- the_help = GetResource('HELP',
- h.help_id[cell_num]);
- buf_size = SizeResource(the_help);
- }
- else /* no topic selected so no help */
- buf_size = 0;
- if (buf_size > 0)
- {
- HLock(the_help);
- TEInsert(*the_help, (long)buf_size,
- h.text);
- HUnlock(the_help);
- }
-
- /* reset the scroll bar */
- SetCtlValue(h.text_scroll, 0);
- /* reposition the help text */
- delta = h.offset -
- GetCtlValue(h.text_scroll);
- TEScroll(0, delta, h.text);
- h.offset -= delta;
- /* scroll bar necessary? */
- if ((*h.text)->nLines > h.lines_vis)
- {
- HiliteControl(h.text_scroll,
- ACTIVATE);
- h.max_text = (((*h.text)->nLines) -
- h.lines_vis) *
- (*h.text)->lineHeight;
- SetCtlMax(h.text_scroll, h.max_text);
- }
- else
- HiliteControl(h.text_scroll,
- INACTIVATE);
- /* finally, save the new topic */
- h.last_one = cell_num;
- }
- return TRUE;
- }
- return FALSE;
-
- default:
- return FALSE;
- }
- }
-
- /************************************************
- * This routine is called by the Toolbox while
- * executing the TrackControl() routine. It has
- * to take care of scrolling the text when the
- * up/down arrow and page parts of the scrollbar
- * are clicked in. */
- pascal void help_action(the_scroll, partcode)
- ControlHandle the_scroll;
- int partcode;
- {
- int value, delta;
-
- switch (partcode)
- {
- case inUpButton:
- value = GetCtlValue(the_scroll);
- value = (value-(*h.text)->lineHeight > 0)
- ? value-(*h.text)->lineHeight
- : 0;
- SetCtlValue(the_scroll, value);
- break;
- case inPageUp: /* move 6 lines at a time */
- value = GetCtlValue(the_scroll);
- value = (value-6*(*h.text)->lineHeight > 0)
- ? value-6*(*h.text)->lineHeight
- : 0;
- SetCtlValue(the_scroll, value);
- break;
- case inDownButton:
- value = GetCtlValue(the_scroll);
- value = (value + (*h.text)->lineHeight <
- h.max_text)
- ? value + (*h.text)->lineHeight
- : h.max_text;
- SetCtlValue(the_scroll, value);
- break;
- case inPageDown:/* move 6 lines at a time */
- value = GetCtlValue(the_scroll);
- value = (value + 6*(*h.text)->lineHeight <
- h.max_text)
- ? value + 6*(*h.text)->lineHeight
- : h.max_text;
- SetCtlValue(the_scroll, value);
- break;
- }
-
- delta = h.offset - GetCtlValue(h.text_scroll);
- TEScroll(0, delta, h.text);
- h.offset -= delta;
- }